﻿/***************************************************
//  Copyright (c) Premium Tax Free 2011
***************************************************/

using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.IO;

namespace PremierTaxFree.PTFLib.Data
{
    public interface IReadable
    {
        void Load(IDataReader reader);
    }

    public interface IBinaryReadable
    {
        void Read(BinaryReader stream);
    }

    public static class SQL
    {
        public static List<T> ExecuteReader<T>(string connString, string sql, params SqlParameter[] paramArray) 
            where T: IReadable, new()
        {
            using (SqlConnection conn = new SqlConnection(connString))
            {
                conn.Open();

                using (SqlCommand comm = new SqlCommand(sql, conn))
                {
                    if (paramArray != null && paramArray.Length > 0)
                        comm.Parameters.AddRange(paramArray);

                    List<T> results = new List<T>();
                    IDataReader reader = comm.ExecuteReader();
                    while (reader.Read())
                    {
                        T t = new T();
                        t.Load(reader);
                        results.Add(t);
                    }
                    return results;
                }
            }
        }

        public static int ExecuteNonQuery(string connString, string sql, params SqlParameter[] paramArray)
        {
            using (SqlConnection conn = new SqlConnection(connString))
            {
                conn.Open();

                using (SqlCommand comm = new SqlCommand(sql, conn))
                {
                    if (paramArray != null && paramArray.Length > 0)
                        comm.Parameters.AddRange(paramArray);

                    return comm.ExecuteNonQuery();
                }
            }
        }

        public static void ExecuteTable(string connString, string tableName, DataTable table)
        {
            using (SqlBulkCopy copy = new SqlBulkCopy(connString, SqlBulkCopyOptions.CheckConstraints))
            {
                copy.DestinationTableName = tableName;
                copy.WriteToServer(table);
            }
        }

        public static SqlCommand CreateCommand(string connString, string sql, params SqlParameter[] paramArray)
        {
            SqlConnection conn = new SqlConnection(connString);
            SqlCommand comm = new SqlCommand(sql, conn);
            if (paramArray != null && paramArray.Length > 0)
                comm.Parameters.AddRange(paramArray);
            return comm;
        }

        /// <summary>
        /// The method can suppress exceptions throwing.
        /// It's used when it logs exceptions to the database.
        /// Logging procedure should not throw exceptions at all 
        /// otherwise it will go into cycle.
        /// </summary>
        /// <param name="comm"></param>
        /// <param name="Throw"></param>
        /// <returns></returns>
        public static int ExecuteNonQuery(SqlCommand comm, bool Throw)
        {
            Debug.Assert(comm != null);
            Debug.Assert(comm.Connection != null);

            try
            {
                using (IDbConnection conn = comm.Connection)
                {
                    conn.Open();

                    using (comm)
                    {
                        return comm.ExecuteNonQuery();
                    }
                }
            }
            catch
            {
                if (Throw)
                    throw;
                return 0;
            }
        }
    }
}
